package com.bookocean.infrastructure.persistence.repository;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.bookocean.application.exception.BusinessException;
import com.bookocean.application.exception.WeChatErrorCodeEnum;
import com.bookocean.controller.dto.NovelDto;
import com.bookocean.controller.dto.NovelChapterDto;
import com.bookocean.controller.dto.NovelParticipantDto;
import com.bookocean.domain.constant.TargetType;
import com.bookocean.domain.repository.NovelRepository;
import com.bookocean.domain.repository.BookLikeRepository;
import com.bookocean.domain.repository.BookCommentRepository;
import com.bookocean.domain.repository.BookFavoriteRepository;
import com.bookocean.infrastructure.persistence.converter.NovelConverter;
import com.bookocean.infrastructure.persistence.mapper.NovelMapper;
import com.bookocean.infrastructure.persistence.mapper.NovelChapterMapper;
import com.bookocean.infrastructure.persistence.mapper.NovelParticipantMapper;
import com.bookocean.infrastructure.persistence.mapper.UserInfoMapper;
import com.bookocean.infrastructure.persistence.po.NovelPO;
import com.bookocean.infrastructure.persistence.po.NovelChapterPO;
import com.bookocean.infrastructure.persistence.po.NovelParticipantPO;
import com.bookocean.infrastructure.persistence.po.UserInfoPO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 小说仓储实现类
 * 
 * @author BookOcean
 * @since 2024-01-01
 */
@Slf4j
@Repository
@RequiredArgsConstructor
public class NovelRepositoryImpl implements NovelRepository {

    private final NovelMapper novelMapper;
    private final NovelChapterMapper novelChapterMapper;
    private final NovelParticipantMapper novelParticipantMapper;
    private final UserInfoMapper userInfoMapper;
    
    private final BookLikeRepository bookLikeRepository;
    private final BookCommentRepository bookCommentRepository;
    private final BookFavoriteRepository bookFavoriteRepository;

    @Override
    @Transactional
    public NovelDto createNovel(NovelDto novelDto) {
        try {
            NovelPO novelPO = NovelConverter.toPo(novelDto);
            novelPO.setCreatedAt(LocalDateTime.now());
            novelPO.setUpdatedAt(LocalDateTime.now());
            
            novelMapper.insert(novelPO);
            
            return NovelConverter.toDto(novelPO);
        } catch (Exception e) {
            log.error("创建小说失败: {}", e.getMessage(), e);
            throw new BusinessException(WeChatErrorCodeEnum.CREATE_NOVEL_ERROR);
        }
    }

    @Override
    public NovelDto getNovelById(Long novelId) {
        if (ObjectUtil.isEmpty(novelId)) {
            return null;
        }
        
        try {
            NovelPO novelPO = novelMapper.selectById(novelId);
            if (ObjectUtil.isEmpty(novelPO)) {
                return null;
            }
            
            return NovelConverter.toDto(novelPO);
        } catch (Exception e) {
            log.error("查询小说失败, novelId: {}, error: {}", novelId, e.getMessage(), e);
            throw new BusinessException(WeChatErrorCodeEnum.GET_NOVEL_ERROR);
        }
    }

    @Override
    public NovelDto getEnhancedNovelById(Long novelId, Long userId) {
        if (ObjectUtil.isEmpty(novelId)) {
            return null;
        }
        
        try {
            // 获取基础小说信息
            NovelPO novelPO = novelMapper.selectById(novelId);
            if (ObjectUtil.isEmpty(novelPO)) {
                return null;
            }
            
            NovelDto novelDto = NovelConverter.toDto(novelPO);
            
            // 查询创建者信息
            UserInfoPO creatorInfo = userInfoMapper.selectById(novelPO.getCreatorId());
            if (creatorInfo != null) {
                novelDto.setCreatorNickname(creatorInfo.getNickName());
            }
            
            // 统计互动数据
            novelDto.setLikeCount(bookLikeRepository.countByTarget(novelId, TargetType.NOVEL));
            novelDto.setCommentCount(bookCommentRepository.countByTarget(novelId, TargetType.NOVEL));
            novelDto.setFavoriteCount(bookFavoriteRepository.countByTarget(novelId, TargetType.NOVEL));
            
            // 查询用户交互状态（如果用户已登录）
            if (userId != null) {
                novelDto.setIsLiked(bookLikeRepository.isLikedByUser(novelId, TargetType.NOVEL, userId));
                novelDto.setIsFavorited(bookFavoriteRepository.isFavoritedByUser(novelId, TargetType.NOVEL, userId));
                novelDto.setIsParticipant(isParticipant(novelId, userId));
            }
            
            // 查询参与者列表
            novelDto.setParticipants(getNovelParticipants(novelId));
            
            return novelDto;
        } catch (Exception e) {
            log.error("查询小说详情失败, novelId: {}, userId: {}, error: {}", novelId, userId, e.getMessage(), e);
            throw new BusinessException(WeChatErrorCodeEnum.GET_NOVEL_ERROR);
        }
    }

    @Override
    @Transactional
    public NovelDto updateNovel(NovelDto novelDto) {
        try {
            NovelPO novelPO = NovelConverter.toPo(novelDto);
            novelPO.setUpdatedAt(LocalDateTime.now());
            
            novelMapper.updateById(novelPO);
            
            return NovelConverter.toDto(novelPO);
        } catch (Exception e) {
            log.error("更新小说失败, novelId: {}, error: {}", novelDto.getId(), e.getMessage(), e);
            throw new BusinessException(WeChatErrorCodeEnum.UPDATE_NOVEL_ERROR);
        }
    }

    @Override
    @Transactional
    public void deleteNovel(Long novelId) {
        try {
            novelMapper.deleteById(novelId);
        } catch (Exception e) {
            log.error("删除小说失败, novelId: {}, error: {}", novelId, e.getMessage(), e);
            throw new BusinessException(WeChatErrorCodeEnum.DELETE_NOVEL_ERROR);
        }
    }

    @Override
    public List<NovelDto> getUserParticipatedNovels(Long userId, Integer page, Integer pageSize) {
        try {
            Integer offset = (page - 1) * pageSize;
            List<NovelPO> novels = novelMapper.selectUserParticipatingNovels(userId, offset, pageSize);
            
            return novels.stream()
                    .map(novel -> {
                        NovelDto dto = NovelConverter.toDto(novel);
                        // 添加统计数据
                        Long novelId = novel.getNovelId();
                        dto.setLikeCount(bookLikeRepository.countByTarget(novelId, TargetType.NOVEL));
                        dto.setCommentCount(bookCommentRepository.countByTarget(novelId, TargetType.NOVEL));
                        dto.setFavoriteCount(bookFavoriteRepository.countByTarget(novelId, TargetType.NOVEL));
                        return dto;
                    })
                    .collect(Collectors.toList());
        } catch (Exception e) {
            log.error("查询用户参与小说失败, userId: {}, error: {}", userId, e.getMessage(), e);
            throw new BusinessException(WeChatErrorCodeEnum.GET_NOVEL_LIST_ERROR);
        }
    }

    @Override
    public List<NovelDto> getRecruitingNovels(Integer page, Integer pageSize) {
        try {
            Integer offset = (page - 1) * pageSize;
            
            LambdaQueryWrapper<NovelPO> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(NovelPO::getStatus, 1) // 招募中状态
                    .eq(NovelPO::getIsMultiplayer, true) // 多人创作
                    .orderByDesc(NovelPO::getCreatedAt)
                    .last("LIMIT " + offset + ", " + pageSize);
            
            List<NovelPO> novels = novelMapper.selectList(queryWrapper);
            
            return novels.stream()
                    .map(novel -> {
                        NovelDto dto = NovelConverter.toDto(novel);
                        // 添加统计数据
                        Long novelId = novel.getNovelId();
                        dto.setLikeCount(bookLikeRepository.countByTarget(novelId, TargetType.NOVEL));
                        dto.setCommentCount(bookCommentRepository.countByTarget(novelId, TargetType.NOVEL));
                        dto.setFavoriteCount(bookFavoriteRepository.countByTarget(novelId, TargetType.NOVEL));
                        return dto;
                    })
                    .collect(Collectors.toList());
        } catch (Exception e) {
            log.error("查询招募中小说失败, error: {}", e.getMessage(), e);
            throw new BusinessException(WeChatErrorCodeEnum.GET_NOVEL_LIST_ERROR);
        }
    }

    @Override
    public List<NovelDto> getCompletedNovels(Integer page, Integer pageSize) {
        try {
            Integer offset = (page - 1) * pageSize;
            List<NovelPO> novels = novelMapper.selectCompletedNovels(offset, pageSize, "hottest");
            
            return novels.stream()
                    .map(novel -> {
                        NovelDto dto = NovelConverter.toDto(novel);
                        // 添加统计数据
                        Long novelId = novel.getNovelId();
                        dto.setLikeCount(bookLikeRepository.countByTarget(novelId, TargetType.NOVEL));
                        dto.setCommentCount(bookCommentRepository.countByTarget(novelId, TargetType.NOVEL));
                        dto.setFavoriteCount(bookFavoriteRepository.countByTarget(novelId, TargetType.NOVEL));
                        return dto;
                    })
                    .collect(Collectors.toList());
        } catch (Exception e) {
            log.error("查询已完结小说失败, error: {}", e.getMessage(), e);
            throw new BusinessException(WeChatErrorCodeEnum.GET_NOVEL_LIST_ERROR);
        }
    }

    @Override
    @Transactional
    public NovelParticipantDto addParticipant(NovelParticipantDto participantDto) {
        try {
            NovelParticipantPO participantPO = NovelConverter.participantToPo(participantDto);
            participantPO.setStatus(1); // 活跃状态
            participantPO.setJoinedAt(LocalDateTime.now());
            
            novelParticipantMapper.insert(participantPO);
            
            return NovelConverter.participantToDto(participantPO);
        } catch (Exception e) {
            log.error("添加参与者失败, error: {}", e.getMessage(), e);
            throw new BusinessException(WeChatErrorCodeEnum.ADD_PARTICIPANT_ERROR);
        }
    }

    @Override
    public List<NovelParticipantDto> getNovelParticipants(Long novelId) {
        try {
            LambdaQueryWrapper<NovelParticipantPO> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(NovelParticipantPO::getNovelId, novelId)
                    .eq(NovelParticipantPO::getStatus, 1) // 活跃状态
                    .orderByAsc(NovelParticipantPO::getJoinOrder);
            
            List<NovelParticipantPO> participants = novelParticipantMapper.selectList(queryWrapper);
            List<NovelParticipantDto> participantDtos = new ArrayList<>();
            
            for (NovelParticipantPO participant : participants) {
                NovelParticipantDto dto = NovelConverter.participantToDto(participant);
                
                // 查询用户信息
                UserInfoPO userInfo = userInfoMapper.selectById(participant.getUserId());
                if (userInfo != null) {
                    dto.setNickname(userInfo.getNickName());
                    dto.setAvatarUrl(userInfo.getAvatarUrl());
                }
                
                participantDtos.add(dto);
            }
            
            return participantDtos;
        } catch (Exception e) {
            log.error("查询小说参与者失败, novelId: {}, error: {}", novelId, e.getMessage(), e);
            throw new BusinessException(WeChatErrorCodeEnum.GET_PARTICIPANTS_ERROR);
        }
    }

    @Override
    public boolean isParticipant(Long novelId, Long userId) {
        try {
            LambdaQueryWrapper<NovelParticipantPO> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(NovelParticipantPO::getNovelId, novelId)
                    .eq(NovelParticipantPO::getUserId, userId)
                    .eq(NovelParticipantPO::getStatus, 1);
            
            return novelParticipantMapper.selectCount(queryWrapper) > 0;
        } catch (Exception e) {
            log.error("检查参与者身份失败, novelId: {}, userId: {}, error: {}", novelId, userId, e.getMessage(), e);
            return false;
        }
    }

    @Override
    @Transactional
    public NovelChapterDto addChapter(NovelChapterDto chapterDto) {
        try {
            NovelChapterPO chapterPO = NovelConverter.chapterToPo(chapterDto);
            chapterPO.setCreatedAt(LocalDateTime.now());
            
            novelChapterMapper.insert(chapterPO);
            
            return NovelConverter.chapterToDto(chapterPO);
        } catch (Exception e) {
            log.error("添加章节失败, error: {}", e.getMessage(), e);
            throw new BusinessException(WeChatErrorCodeEnum.ADD_CHAPTER_ERROR);
        }
    }

    @Override
    public List<NovelChapterDto> getNovelChapters(Long novelId) {
        try {
            LambdaQueryWrapper<NovelChapterPO> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(NovelChapterPO::getNovelId, novelId)
                    .orderByAsc(NovelChapterPO::getChapterNumber);
            
            List<NovelChapterPO> chapters = novelChapterMapper.selectList(queryWrapper);
            List<NovelChapterDto> chapterDtos = new ArrayList<>();
            
            for (NovelChapterPO chapter : chapters) {
                NovelChapterDto dto = NovelConverter.chapterToDto(chapter);
                
                // 查询作者信息
                UserInfoPO authorInfo = userInfoMapper.selectById(chapter.getAuthorId());
                if (authorInfo != null) {
                    dto.setAuthorNickname(authorInfo.getNickName());
                    dto.setAuthorAvatarUrl(authorInfo.getAvatarUrl());
                }
                
                // 统计互动数据
                Long chapterId = chapter.getChapterId();
                dto.setLikeCount(bookLikeRepository.countByTarget(chapterId, TargetType.CHAPTER));
                dto.setCommentCount(bookCommentRepository.countByTarget(chapterId, TargetType.CHAPTER));
                dto.setFavoriteCount(bookFavoriteRepository.countByTarget(chapterId, TargetType.CHAPTER));
                
                chapterDtos.add(dto);
            }
            
            return chapterDtos;
        } catch (Exception e) {
            log.error("查询小说章节失败, novelId: {}, error: {}", novelId, e.getMessage(), e);
            throw new BusinessException(WeChatErrorCodeEnum.GET_CHAPTERS_ERROR);
        }
    }

    @Override
    public NovelChapterDto getEnhancedChapterById(Long chapterId, Long userId) {
        try {
            NovelChapterPO chapterPO = novelChapterMapper.selectById(chapterId);
            if (ObjectUtil.isEmpty(chapterPO)) {
                return null;
            }
            
            NovelChapterDto chapterDto = NovelConverter.chapterToDto(chapterPO);
            
            // 查询作者信息
            UserInfoPO authorInfo = userInfoMapper.selectById(chapterPO.getAuthorId());
            if (authorInfo != null) {
                chapterDto.setAuthorNickname(authorInfo.getNickName());
                chapterDto.setAuthorAvatarUrl(authorInfo.getAvatarUrl());
            }
            
            // 统计互动数据
            chapterDto.setLikeCount(bookLikeRepository.countByTarget(chapterId, TargetType.CHAPTER));
            chapterDto.setCommentCount(bookCommentRepository.countByTarget(chapterId, TargetType.CHAPTER));
            chapterDto.setFavoriteCount(bookFavoriteRepository.countByTarget(chapterId, TargetType.CHAPTER));
            
            // 查询用户交互状态（如果用户已登录）
            if (userId != null) {
                chapterDto.setIsLiked(bookLikeRepository.isLikedByUser(chapterId, TargetType.CHAPTER, userId));
                chapterDto.setIsFavorited(bookFavoriteRepository.isFavoritedByUser(chapterId, TargetType.CHAPTER, userId));
            }
            
            return chapterDto;
        } catch (Exception e) {
            log.error("查询章节详情失败, chapterId: {}, userId: {}, error: {}", chapterId, userId, e.getMessage(), e);
            throw new BusinessException(WeChatErrorCodeEnum.GET_CHAPTER_ERROR);
        }
    }

    @Override
    public Integer getNextChapterNumber(Long novelId) {
        try {
            return novelChapterMapper.getNextChapterNumber(novelId);
        } catch (Exception e) {
            log.error("获取下一个章节序号失败, novelId: {}, error: {}", novelId, e.getMessage(), e);
            return 1; // 默认返回1
        }
    }

    @Override
    public boolean hasWrittenTodayChapter(Long novelId, Long userId) {
        try {
            LocalDateTime todayStart = LocalDateTime.of(LocalDate.now(), LocalTime.MIN);
            Integer count = novelChapterMapper.countTodayChapters(novelId, userId, todayStart);
            return count > 0;
        } catch (Exception e) {
            log.error("检查今日写作状态失败, novelId: {}, userId: {}, error: {}", novelId, userId, e.getMessage(), e);
            return false;
        }
    }

    @Override
    public Long getNextWriterUserId(Long novelId) {
        try {
            return novelParticipantMapper.getNextWriterUserId(novelId);
        } catch (Exception e) {
            log.error("获取下一个写作者失败, novelId: {}, error: {}", novelId, e.getMessage(), e);
            return null;
        }
    }

    @Override
    public List<Long> getNovelParticipantIds(Long novelId) {
        try {
            List<NovelParticipantDto> participants = getNovelParticipants(novelId);
            return participants.stream()
                    .map(NovelParticipantDto::getUserId)
                    .collect(Collectors.toList());
        } catch (Exception e) {
            log.error("获取小说参与者ID列表失败, novelId: {}, error: {}", novelId, e.getMessage(), e);
            return Collections.emptyList();
        }
    }
}
